﻿// Implementation based on George Marsaglia's MWC (multiply with carry) generator.
// George Marsaglia's MWC (multiply with carry) generator.
// Although it is very simple, it passes Marsaglia's DIEHARD series of random number generator tests.
// 
// Written by John D. Cook 
// http://www.johndcook.com
//
//
// Ported to OpenCL by Christopher J. Hanson
// Added feedback loop to interpolate randomization
// Call PsuedoRandom( &random_t ) for feedback

typedef struct { float Value; uint Seed_w; uint Seed_z; } random_t;

random_t Seed( uint seed )
{
    random_t result;
    result.Value = (float)seed;
    result.Seed_w = seed;
    result.Seed_z = seed;
    return result;
}

void NextUInt( random_t* random )
{
    uint m_w = random->Seed_w;
    uint m_z = random->Seed_z;
    random->Seed_w = 18000 * ( m_w & 65535 ) + ( m_w >> 16 );
    random->Seed_z = 36969 * ( m_z & 65535 ) + ( m_z >> 16 );
    random->Value = ( ( random->Seed_z << 16 ) + random->Seed_w );
}

void NextUniform( random_t* random )
{
    NextUInt( random );
    random->Value = ( random->Value + 1.0f ) * 2.328306435454494e-10;
}

void NextNormal( random_t* random )
{
    NextUniform( random );
    float v1 = random->Value;

    NextUniform( random );
    float v2 = random->Value;

    float r = sqrt( -2.0f * log( v1 ) );
    float theta = ( 2.0f * 3.1415926535897931 ) * v2;
    random->Value = r * sin( theta );

}

void PsuedoRandom( random_t* random, uint loops )
{
    loops %= 4;
    for( int index = 0; index < loops; index++ )
        NextUInt( random );
    NextUniform( random );
    loops = (uint)(random->Value * 10);
    loops %= 10;
    for( int index = 0; index < loops; index++ )
        NextUInt( random );
}